﻿using Newtonsoft.Json;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;

using System.Drawing;
using System.Drawing.Imaging;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using ZXing;
using ZXing.Common;
using ZXing.QrCode;

namespace KWT.DRG_DIP.Common
{

    /// <summary>
    /// 扩展方法
    /// </summary>
    public static class _Ext
    {
        public static string ToNumberStr(this int src)
        {
            if (src >= 10000 && src < 100000000)
            {
                return Math.Round((decimal)(src / 10000), 2, MidpointRounding.ToNegativeInfinity).ToString() + "万";
            }
            if (src >= 100000000)
            {
                return Math.Round((decimal)(src / 100000000), 2, MidpointRounding.ToNegativeInfinity).ToString() + "亿";
            }
            return src.ToString();
        }

        public static string ToNumberStr(this decimal src)
        {
            if (src >= 10000 && src < 100000000)
            {
                return Math.Round((src / 10000), 2, MidpointRounding.ToNegativeInfinity).ToString() + "万";
            }
            if (src >= 100000000)
            {
                return Math.Round((src / 100000000), 2, MidpointRounding.ToNegativeInfinity).ToString() + "亿";
            }
            return src.ToString();
        }
        /// <summary>
        /// 本时区日期时间转时间戳
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns>long=Int64</returns>
        public static long DateTimeToTimestamp(this DateTime datetime)
        {
            DateTime dd = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            DateTime timeUTC = datetime.ToUniversalTime();
            TimeSpan ts = (timeUTC - dd);
            return (long)ts.TotalMilliseconds;//精确到毫秒

        }
        public static byte[] ToBytes(this IntPtr pointer, int length)
        {
            if (length <= 0 || pointer == IntPtr.Zero)
            {
                return null;
            }
            var b = new byte[length];
            Marshal.Copy(pointer, b, 0, length);
            return b;
        }

        public static async Task<byte[]> ToBytesAsync(this System.Drawing.Image img)
        {
            using var stream = new MemoryStream();
            var bmp = new Bitmap(img);
            bmp.Save(stream, ImageFormat.Jpeg);

            var b = new byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            await stream.ReadAsync(b, 0, b.Length);
            stream.Dispose();
            await stream.DisposeAsync();
            stream.Close();
            return b;
        }

        public static async Task<byte[]> ToBytesAsync(this Bitmap bitmap)
        {
            using var stream = new MemoryStream();
            bitmap.Save(stream, ImageFormat.Jpeg);
            var b = new byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            await stream.ReadAsync(b, 0, b.Length);
            stream.Dispose();
            await stream.DisposeAsync();
            stream.Close();
            return b;
        }

        public static string ToJson(this object obj) => JsonConvert.SerializeObject(obj);

        public static T ToObject<T>(this string json) => JsonConvert.DeserializeObject<T>(json);

        public static (bool, string) ToImg(this string base64, string uploadPath, out string imgName)
        {
            if (string.IsNullOrEmpty(base64))
            {
                imgName = "";
                return (false, "base64为空");
            }
            try
            {
                var arr = base64.Split(',');
                string mime = arr[0].Split(';')[0].Split(':')[1];
                byte[] bytes = Convert.FromBase64String(arr[1]);
                using var ms = new MemoryStream(bytes);
                var bmp = new Bitmap(ms);
                if (!Directory.Exists(uploadPath))
                {
                    Directory.CreateDirectory(uploadPath);
                }
                ImageFormat format;
                string guid = Guid.NewGuid().ToString();
                string ext;
                switch (mime)
                {
                    case "image/png":
                        format = ImageFormat.Png;
                        ext = ".png";
                        break;
                    case "image/jpeg":
                        format = ImageFormat.Jpeg;
                        ext = ".jpg";
                        break;
                    case "image/gif":
                        format = ImageFormat.Gif;
                        ext = ".gif";
                        break;
                    default:
                        format = ImageFormat.Bmp;
                        ext = ".bmp";
                        break;
                }
                imgName = guid + ext;
                string filePath = Path.Combine(uploadPath, imgName);
                bmp.Save(filePath, format);
                return (true, "转换成功");
            }
            catch (Exception ex)
            {
                imgName = "";
                return (false, "转换失败:" + ex.Message);
            }
        }

        public static List<T> ToPageList<T>(this IQueryable<T> q, int page, int size) => q.Skip(size * (page - 1)).Take(size).ToList();

        public static System.Drawing.Image ToImage(this byte[] bytes)
        {
            using var ms = new MemoryStream(bytes);
            ms.Write(bytes, 0, bytes.Length);
            var img = System.Drawing.Image.FromStream(ms, true);
            return img;
        }


        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="value">value</param>
        /// <param name="width">二维码宽，默认500</param>
        /// <param name="height">二维码高，默认500</param>
        public static Stream ToQrCode(this string value, int width = 500, int height = 500)
        {
            var w = new QRCodeWriter();
            BitMatrix b = w.encode(value, BarcodeFormat.QR_CODE, width, height);
            var zzb = new ZXing.ImageSharp.BarcodeWriter<Rgba32>
            {
                Options = new EncodingOptions()
                {
                    Margin = 0,
                }
            };
            var ms = new MemoryStream();
            using (var image = zzb.Write(b))
            {

                image.SaveAsPng(ms);
            }
            ms.Position = 0;//设置位置
            return ms;
        }

        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="value">value</param>
        /// <param name="width">二维码宽，默认500</param>
        /// <param name="height">二维码高，默认500</param>
        public static Stream ToQrCodeLinux(this string value, int width = 500, int height = 500)
        {
            var writer = new ZXing.ImageSharp.BarcodeWriter<Rgba32>
            {
                Format = BarcodeFormat.QR_CODE,
                Options = new ZXing.QrCode.QrCodeEncodingOptions
                {
                    DisableECI = true,
                    CharacterSet = "UTF-8",
                    Width = width,
                    Height = height,
                    Margin = 1
                }
            };
            var image = writer.WriteAsImageSharp<Rgba32>(value);
            var ms = new MemoryStream();
            image.Save(ms, new PngEncoder());
            return ms;
        }
    }
}
